package com.jyserver.common.AutoCode;


import com.jyserver.common.utils.HelpUtils;
import com.jyserver.common.utils.Replaces;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.JavaTypeResolver;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.config.*;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.mybatis.generator.internal.db.DatabaseIntrospector;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

public class AutoCodeStartUp {
    private Logger logger = Logger.getLogger(AutoCodeStartUp.class);

    public static Configuration config = null;
    public static Context context = null;
    public static MyBatisGenerator myBatisGenerator = null;
    private static Properties properties = new Properties();


    public void generate() {
        try {
            getconfig();
            List<String> warnings = new ArrayList<String>();
            boolean overwrite = true;
            if (!Boolean.valueOf(properties.getProperty("only_table"))) {
                System.err.println("开始执行任务");
                DefaultShellCallback callback = new DefaultShellCallback(overwrite);
                myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
//                myBatisGenerato
//                myBatisGenerator.getGeneratedJavaFiles().get(0).get
                myBatisGenerator.generate(null);
                System.err.println("任务结束");
            } else {

                System.err.println("需要编译全部数据表");
                Connection conn = DriverManager.getConnection(properties.getProperty("connectionURL"), properties.getProperty("userId"), properties.getProperty("password"));
                // 获取数据库元数据
                DatabaseMetaData metaData = conn.getMetaData();
                JavaTypeResolver javalver = new JavaTypeResolver() {
                    @Override
                    public void addConfigurationProperties(Properties properties) {

                    }

                    @Override
                    public void setContext(Context context) {

                    }

                    @Override
                    public void setWarnings(List<String> warnings) {

                    }

                    @Override
                    public FullyQualifiedJavaType calculateJavaType(IntrospectedColumn introspectedColumn) {
                        return null;
                    }

                    @Override
                    public String calculateJdbcTypeName(IntrospectedColumn introspectedColumn) {
                        return null;
                    }
                };
                DatabaseIntrospector databaseIntrospector = new DatabaseIntrospector(context, metaData, javalver, warnings);
                List<TableConfiguration> tableConfigurations = context.getTableConfigurations();
                TableConfiguration tc = new TableConfiguration(context);
                for (int n = 0; n < tableConfigurations.size() - 1; n++) {
                    try {
                        tc.setTableName(tableConfigurations.get(n).getTableName());
                        List<IntrospectedTable> introspectedTables = databaseIntrospector.introspectTables(tc);
                        IntrospectedTable arg1 = introspectedTables.get(0);
                        if (Boolean.valueOf(context.getProperty("GeneratorWeb_enable"))) {
                            GeneratorWeb(arg1);
                        }
//                    if (Boolean.valueOf(context.getProperty("GeneratorController_enable"))) {
//                        GeneratorController(arg1);
//                    }
                    } catch (Exception e) {

                    }
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (InvalidConfigurationException e) {
            e.printStackTrace();
            e.printStackTrace();
        }
    }

    public void getconfig() throws IOException {
        System.err.println("获取配置");
        getProperty();
        try {
            List<String> warnings = new ArrayList<String>();
            boolean overwrite = true;
            /**7
             *@Description :配置注解类
             */
            context = new Context(null);
            config = new Configuration();
            context.setId("DB2Tables");
            context.setTargetRuntime("MyBatis3");

            CommentGeneratorConfiguration com = new CommentGeneratorConfiguration();
            com.addProperty("suppressAllComments", properties.getProperty("suppressAllComments"));
            com.setConfigurationType(properties.getProperty("ConfigurationType"));
            context.setCommentGeneratorConfiguration(com);


            PluginConfiguration pluginC = new PluginConfiguration();
            pluginC.setConfigurationType(properties.getProperty("pluginConfiguration"));
            if (HelpUtils.isNotEmpty(properties.getProperty("common_targetPackage"))) {
                String common_targetPackage = properties.getProperty("common_targetPackage");
                properties.setProperty("javaModelGenerator_targetPackage", common_targetPackage + ".dao.model");
                properties.setProperty("sqlmap_targetPackage", common_targetPackage + ".mapper.sql");
                properties.setProperty("javaclient_targetPackage", common_targetPackage + ".mapper");
                properties.setProperty("javaclient_targetPackage", common_targetPackage + ".mapper");
                properties.setProperty("GeneratorController_targetPackage", common_targetPackage + ".controller");
                if (HelpUtils.isEmpty(properties.getProperty("GeneratorWeb_targetPackage"))) {
                    properties.setProperty("GeneratorWeb_targetPackage", common_targetPackage + ".web");
                }
            }
            context.addPluginConfiguration(pluginC);

            /**
             *@Description :数据库连接
             */
            JDBCConnectionConfiguration jdbc = new JDBCConnectionConfiguration();
            jdbc.setDriverClass(properties.getProperty("driverClass"));
            jdbc.setConnectionURL(properties.getProperty("connectionURL"));
            jdbc.setPassword(properties.getProperty("password"));
            jdbc.setUserId(properties.getProperty("userId"));
            jdbc.addProperty("useInformationSchema", "true");
            context.setJdbcConnectionConfiguration(jdbc);


            /**
             *@Description :javaTypeResolver
             */
            JavaTypeResolverConfiguration javatype = new JavaTypeResolverConfiguration();

            javatype.addProperty("forceBigDecimals", properties.getProperty("forceBigDecimals"));
            context.setJavaTypeResolverConfiguration(javatype);

            /**
             *@Description :javaModelGenerator
             */
            JavaModelGeneratorConfiguration javaModelGenerator = new JavaModelGeneratorConfiguration();
            javaModelGenerator.setTargetPackage(properties.getProperty("javaModelGenerator_targetPackage"));
            javaModelGenerator.setTargetProject(properties.getProperty("javaModelGenerator_targetProject"));
            javaModelGenerator.addProperty("enableSubPackages", properties.getProperty("javaModelGenerator_enableSubPackages"));
            javaModelGenerator.addProperty("trimStrings", properties.getProperty("javaModelGenerator_trimStrings"));
            context.setJavaModelGeneratorConfiguration(javaModelGenerator);

            /**
             *@Description :sqlmap
             */
            SqlMapGeneratorConfiguration sqlmap = new SqlMapGeneratorConfiguration();
            sqlmap.setTargetPackage(properties.getProperty("sqlmap_targetPackage"));
            sqlmap.setTargetProject(properties.getProperty("sqlmap_targetProject"));
            sqlmap.addProperty("enableSubPackages", properties.getProperty("sqlmap_enableSubPackages"));
            context.setSqlMapGeneratorConfiguration(sqlmap);

            /**
             *@Description :javaclient
             */
            JavaClientGeneratorConfiguration javaclient = new JavaClientGeneratorConfiguration();
            javaclient.setTargetProject(properties.getProperty("javaclient_targetProject"));
            javaclient.setTargetPackage(properties.getProperty("javaclient_targetPackage"));
            javaclient.setConfigurationType(properties.getProperty("javaclient_type"));
            javaclient.addProperty("enableSubPackages", properties.getProperty("javaclient_enableSubPackages"));
            context.setJavaClientGeneratorConfiguration(javaclient);


            /**
             *@Description :TableConfiguration
             */
            String tablename = null;
            if (properties.getProperty("alltable").equals("true") && HelpUtils.isNotEmpty(properties.getProperty("database"))) {
                String[] TablesName = new String[]{};
                Class.forName(properties.getProperty("driverClass"));
                Connection con = DriverManager.getConnection(properties.getProperty("connectionURL"), properties.getProperty("userId"), properties.getProperty("password"));
                String sql = null;
                Statement statement = con.createStatement();
                if (properties.getProperty("driverClass").contains("mysql")) {
                    sql = "select TABLE_NAME as 'tablename' from information_schema.TABLES where table_schema = '" + properties.getProperty("database") + "';";
                } else if (properties.getProperty("driverClass").contains("postgresql")) {
                    sql = "SELECT   tablename   FROM   pg_tables  WHERE   tablename   NOT   LIKE   'pg%'  AND tablename NOT LIKE 'sql_%' ORDER   BY   tablename;";
                } else if (properties.getProperty("driverClass").contains("oracle")) {
                    sql = "select t.table_name from user_tables t;";
                }
                ResultSet rs = statement.executeQuery(sql);
                while (rs.next()) {
                    tablename = rs.getString("tablename");
                    Context cont = new Context(null);
                    TableConfiguration table = new TableConfiguration(cont);
                    table.setTableName(tablename);
                    table.setDomainObjectName(properties.getProperty("DomainObjectName") + Replaces.toUpperCaseFirstOne(Replaces.StringFilter(tablename)));
                    table.setUpdateByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableUpdateByExample")));
                    table.setCountByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableCountByExample")));
                    table.setDeleteByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableDeleteByExample")));

                    table.setSelectByExampleQueryId(properties.getProperty("selectByExampleQueryId"));
                    table.setSelectByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableSelectByExample")));
                    table.setInsertStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableInsert")));
                    context.addTableConfiguration(table);
                }
                rs.close();
                con.close();
            } else {
                String[] tables = properties.getProperty("alltable").split(",");
                for (int i = 0; i < tables.length; i++) {
                    tablename = tables[i];
                    Context cont = new Context(null);
                    TableConfiguration table = new TableConfiguration(cont);
                    table.setTableName(tablename);
                    table.setDomainObjectName(properties.getProperty("DomainObjectName") + Replaces.toUpperCaseFirstOne(Replaces.StringFilter(tablename)));
                    table.setUpdateByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableUpdateByExample")));
                    table.setCountByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableCountByExample")));
                    table.setDeleteByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableDeleteByExample")));

                    table.setInsertStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableDeleteByExample")));

                    table.setSelectByPrimaryKeyQueryId("id");

                    table.setSelectByExampleQueryId(properties.getProperty("selectByExampleQueryId"));
                    table.setSelectByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableSelectByExample")));
                    table.setInsertStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableInsert")));
                    context.addTableConfiguration(table);
                }
            }


            /**
             *@Description :ViewConfiguration
             */
            String viewname = null;
            if (properties.getProperty("allview").equals("true")) {
                String[] TablesName = new String[]{};
                Class.forName(properties.getProperty("driverClass"));
                Connection con = DriverManager.getConnection(properties.getProperty("connectionURL"), properties.getProperty("userId"), properties.getProperty("password"));
                String sql = null;
                Statement statement = con.createStatement();
                if (properties.getProperty("driverClass").contains("mysql")) {
                    sql = "select TABLE_NAME as 'tablename' from information_schema.TABLES where table_schema = '" + properties.getProperty("database") + "';";
                } else if (properties.getProperty("driverClass").contains("postgresql")) {
                    sql = " SELECT  " +
                            "viewname   FROM   pg_views  WHERE     schemaname ='public';";
                } else if (properties.getProperty("driverClass").contains("oracle")) {
                    sql = "select t.table_name from user_tables t;";
                }
                ResultSet rs = statement.executeQuery(sql);
                while (rs.next()) {
                    viewname = rs.getString("viewname");
                    if (viewname.indexOf("query") != -1) {

                        Context cont = new Context(null);
                        TableConfiguration table = new TableConfiguration(cont);
                        table.setTableName(viewname);
                        table.setDomainObjectName(properties.getProperty("DomainObjectName") + Replaces.toUpperCaseFirstOne(Replaces.StringFilter(viewname)));
                        table.setUpdateByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableUpdateByExample")));
                        table.setCountByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableCountByExample")));
                        table.setDeleteByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableDeleteByExample")));

                        table.setSelectByExampleQueryId(properties.getProperty("selectByExampleQueryId"));
                        table.setSelectByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableSelectByExample")));
                        table.setInsertStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableInsert")));
                        context.addTableConfiguration(table);
                    }
                }
                rs.close();
                con.close();
            } else {
                String[] tables = properties.getProperty("allview").split(",");
                for (int i = 0; i < tables.length; i++) {
                    viewname = tables[i];
                    Context cont = new Context(null);
                    TableConfiguration table = new TableConfiguration(cont);
                    table.setTableName(viewname);
                    table.setDomainObjectName(properties.getProperty("DomainObjectName") + Replaces.toUpperCaseFirstOne(Replaces.StringFilter(viewname)));
                    table.setUpdateByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableUpdateByExample")));
                    table.setCountByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableCountByExample")));
                    table.setDeleteByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableDeleteByExample")));

                    table.setInsertStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableDeleteByExample")));

                    table.setSelectByExampleQueryId(properties.getProperty("selectByExampleQueryId"));
                    table.setSelectByExampleStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableSelectByExample")));
                    table.setInsertStatementEnabled(Boolean.parseBoolean(properties.getProperty("enableInsert")));
                    context.addTableConfiguration(table);
                }
            }

            context.addProperty("GeneratorController", properties.getProperty("GeneratorController"));
            context.addProperty("GeneratorWeb", properties.getProperty("GeneratorWeb"));

            context.addProperty("GeneratorController_targetPackage", properties.getProperty("GeneratorController_targetPackage"));
            context.addProperty("GeneratorController_enable", properties.getProperty("GeneratorController_enable"));

            context.addProperty("GeneratorWeb_targetPackage", properties.getProperty("GeneratorWeb_targetPackage"));
            context.addProperty("GeneratorWeb_enable", properties.getProperty("GeneratorWeb_enable"));

            context.addProperty("controllerhead", properties.getProperty("controllerhead"));

            config.addContext(context);
//            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
//            myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
//            myBatisGenerator.generate(null);
        } catch (SQLException e) {
            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        } catch (InvalidConfigurationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    private void setdefaultProperty() {
        properties.put("suppressAllComments", "true");
        properties.put("ConfigurationType", "com.jyserver.common.AutoCode.jybaits.MyCommentGenerator");
        properties.put("suppressDate", "true");
        properties.put("MyBatisType", "MyBatis3");
        properties.put("driverClass", "com.mysql.jdbc.Driver");
        properties.put("connectionURL", "connectionURL");
        properties.put("userId", "root");
        properties.put("password", "root");
        properties.put("forceBigDecimals", "false");
        properties.put("javaModelGenerator_targetPackage", "com.test.dao.model");
        properties.put("javaModelGenerator_targetProject", "src/main/java");
        properties.put("javaModelGenerator_trimStrings", "true");
        properties.put("javaModelGenerator_enableSubPackages", "true");


        properties.put("sqlmap_targetPackage", "com.test.mapper.sql");
        properties.put("sqlmap_targetProject", "src/main/java");
        properties.put("sqlmap_enableSubPackages", "true");

        properties.put("javaclient_targetPackage", "com.test.mapper");
        properties.put("javaclient_targetProject", "src/main/java");
        properties.put("javaclient_type", "XMLMAPPER");
        properties.put("javaclient_enableSubPackages", "true");

        properties.put("alltable", "false");
        properties.put("forceBigDecimals", "false");

        properties.put("DomainObjectName", "");
        properties.put("enableCountByExample", "true");
        properties.put("enableUpdateByExample", "false");
        properties.put("enableDeleteByExample", "false");
        properties.put("enableSelectByExample", "true");
        properties.put("selectByExampleQueryId", "true");
        properties.put("enableInsert", "true");

        properties.put("GeneratorController", "com.jyserver.common.AutoCode.jybaits.GeneratorController");
        properties.put("GeneratorController_targetPackage", "com.test.controller");

        properties.put("GeneratorWeb", "com.jyserver.common.AutoCode.jybaits.GeneratorWeb");
        properties.put("GeneratorWeb_targetPackage", "com.test.web");
        properties.put("pluginConfiguration", "com.jyserver.common.AutoCode.jybaits.PaginationPlugin");

        properties.put("controllerhead", "controller"); //控制器头部
        properties.put("GeneratorController_enable", "true");

        properties.put("GeneratorWeb_enable", "true");
        properties.put("allview", "false");

        properties.put("only_table", "false");

        // @Description:信息验证
        properties.put("RequiresRoles", "false");
        properties.put("RequiresPermissions", "false");
    }

    @Test
    public void getProperty() {
        setdefaultProperty();
        Properties prop = new Properties();
        try {
            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            System.out.println("获取配置文件数据流");
            InputStream in = classloader.getResourceAsStream("generator.properties");
            prop.load(in);
            Iterator<String> it = prop.stringPropertyNames().iterator();
            while (it.hasNext()) {
                String key = it.next();
                if (HelpUtils.isEmpty(properties.getProperty(key))) {
                    properties.put(key, prop.getProperty(key));
                } else {
                    properties.setProperty(key, prop.getProperty(key));
                }
            }
        } catch (Exception e) {
        }
    }


    private void GeneratorController(IntrospectedTable arg1) {

        System.out.println("获取GeneratorController控制类");
        //获取GeneratorController的java类
        String className = context.getProperty("GeneratorController");
        String methodName = "GeneratorController";
        Class clz = null;
        try {
            clz = Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //
        Object obj = null;
        try {
            obj = clz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        //获取方法
        java.lang.reflect.Method m = null;
        try {
            m = obj.getClass().getDeclaredMethod(methodName, IntrospectedTable.class, String.class, String.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        //调用方法
        String result = null;
        try {
            System.err.println(context.getProperty("GeneratorController_targetPackage") + "调用方法");
            result = (String) m.invoke(obj, arg1, context.getProperty("GeneratorController_targetPackage"), context.getProperty("controllerhead"));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private void GeneratorWeb(IntrospectedTable arg1) {
        String className = context.getProperty("GeneratorWeb");
        String methodName = "GeneratorWeb";
        Class clz = null;
        try {
            clz = Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //
        Object obj = null;
        try {
            obj = clz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        //获取方法
        java.lang.reflect.Method m = null;
        try {
            m = obj.getClass().getDeclaredMethod(methodName, IntrospectedTable.class, String.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        //调用方法
        String result = null;
        try {
            result = (String) m.invoke(obj, arg1, context.getProperty("GeneratorWeb_targetPackage"));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
